package com.qishenyuan.competition.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qishenyuan.competition.exception.BusinessErrorType;
import com.qishenyuan.competition.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.util.Map;

@Slf4j
public class JacksonUtil {

    static ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 对象转json
     *
     * @return 失败返回null
     */
    public static String toJson(Object obj) {
        try {
            return OBJECT_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("Failed to serialize the object:{} to json.", obj, e);
        }
        return null;
    }

    /**
     * json转Map
     *
     * @return 失败返回null
     */
    public static <T> Map toMap(String json) {
        try {
            return OBJECT_MAPPER.readValue(json, Map.class);
        } catch (Exception e) {
            log.error("Failed to deserialize the json:{} to map.", json, e);
        }
        return null;
    }

    /**
     * 对象转map
     */
    @SuppressWarnings("unchecked")
    public static <T> Map<String, T> toMap(Object obj) {
        return toMap(toJson(obj));
    }

    /**
     * json转对象
     *
     * @return 失败返回null
     */
    public static <T> T toObject(String json, Class<T> targetClass) {
        try {
            return OBJECT_MAPPER.readValue(json, targetClass);
        } catch (Exception e) {
            log.error("Failed to deserialize the json:{} to the class:{}.", json, targetClass, e);
        }
        return null;
    }

    /**
     * json转对象
     *
     * @param json
     * @return 失败返回null
     */
    public static <T> T toObject(String json, TypeReference<T> typeReference) {
        try {
            return OBJECT_MAPPER.readValue(json, typeReference);
        } catch (Exception e) {
            log.error("Failed to deserialize the json:{} to the class:{}.", json, typeReference, e);
        }
        return null;
    }

    /**
     * 把某个对象转为另外一个对象
     *
     * @param <T>
     * @param obj         原对象
     * @param targetClass 目标对象类定义
     */
    public static <T> T toObject(Object obj, Class<T> targetClass) {
        return toObject(toJson(obj), targetClass);
    }

    public static <T> T toObject(InputStream stream, Class<T> targetClass){
        try {
            return OBJECT_MAPPER.readValue(stream, targetClass);
        }catch (Exception e){
            log.warn("jackson toObject fail",e);
            throw new BusinessException(BusinessErrorType.SYSTEM_ERROR);
        }
    }

    public static <T> T toObject(Object obj, TypeReference<T> typeReference) {
        try {
            return  OBJECT_MAPPER.convertValue(obj, typeReference);
        } catch (Exception e) {
            log.error("Failed to deserialize the to the class:{}.", typeReference, e);
        }
        return null;
    }
}
